use codegraph_analytics::{
    AdvancedAnalyzer, AnalysisConfig, CodeMetrics, TrendAnalyzer, TrendConfig,
    ComplexityAnalyzer, ComplexityConfig, QualityAnalyzer, QualityConfig,
};
use std::collections::HashMap;
use std::path::Path;
use tokio::fs;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Initialize logging
    tracing_subscriber::fmt::init();

    println!("🚀 CodeGraph-RT Advanced Analytics Demo");
    println!("======================================");

    // Create a temporary project for demonstration
    let project_path = std::env::temp_dir().join("analytics_demo");

    // Create sample files
    fs::create_dir_all(&project_path).await?;
    create_sample_project(&project_path).await?;

    // 1. Basic Analytics Demo
    println!("\n1. Basic Code Analytics...");
    demo_basic_analytics(&project_path).await?;

    // 2. Complexity Analysis Demo
    println!("\n2. Complexity Analysis...");
    demo_complexity_analysis().await?;

    // 3. Quality Analysis Demo
    println!("\n3. Quality Analysis...");
    demo_quality_analysis().await?;

    // 4. Trend Analysis Demo
    println!("\n4. Trend Analysis...");
    demo_trend_analysis().await?;

    // 5. Comprehensive Report Demo
    println!("\n5. Comprehensive Report Generation...");
    demo_comprehensive_report(&project_path).await?;

    println!("\n🎉 Analytics Demo Complete!");
    println!("=====================================");
    println!("Demonstrated features:");
    println!("• ✅ Advanced code metrics calculation");
    println!("• ✅ Complexity analysis (cyclomatic, cognitive, Halstead)");
    println!("• ✅ Quality assessment and issue detection");
    println!("• ✅ Trend analysis and forecasting");
    println!("• ✅ Comprehensive report generation");
    println!("• ✅ Multiple output formats (JSON, HTML, Markdown, CSV)");

    Ok(())
}

async fn create_sample_project(project_path: &Path) -> Result<(), Box<dyn std::error::Error>> {
    // Create a sample Python file with various complexity patterns
    let python_code = r#"
import os
import sys
from typing import List, Dict, Optional

class DataProcessor:
    """A sample class for data processing with various complexity patterns."""
    
    def __init__(self, config: Dict[str, str]):
        self.config = config
        self.data = []
        self.processed_count = 0
    
    def process_data(self, input_data: List[Dict]) -> List[Dict]:
        """Process input data with complex logic."""
        results = []
        
        for item in input_data:
            # Complex nested conditions (high cyclomatic complexity)
            if item.get('type') == 'A':
                if item.get('priority') == 'high':
                    if item.get('status') == 'active':
                        if self._validate_item(item):
                            processed = self._process_type_a(item)
                            if processed:
                                results.append(processed)
                        else:
                            self._log_error(f"Invalid item: {item}")
                    elif item.get('status') == 'pending':
                        self._queue_for_later(item)
                elif item.get('priority') == 'medium':
                    if self._should_process_medium(item):
                        results.append(self._process_medium(item))
            elif item.get('type') == 'B':
                # More complex logic
                try:
                    result = self._complex_calculation(item)
                    if result > 0:
                        results.append({'result': result, 'original': item})
                    elif result == 0:
                        self._handle_zero_result(item)
                    else:
                        self._handle_negative_result(item)
                except Exception as e:
                    self._log_error(f"Processing error: {e}")
                    continue
            
            self.processed_count += 1
        
        return results
    
    def _validate_item(self, item: Dict) -> bool:
        """Validate an item with multiple checks."""
        # Magic numbers (code smell)
        if len(item.get('data', '')) < 5:
            return False
        if item.get('value', 0) > 1000:
            return False
        if item.get('timestamp', 0) < 1609459200:  # Hardcoded timestamp
            return False
        return True
    
    def _process_type_a(self, item: Dict) -> Optional[Dict]:
        """Process type A items."""
        # Duplicated code pattern
        result = {}
        result['id'] = item.get('id')
        result['processed_at'] = self._get_timestamp()
        result['status'] = 'completed'
        result['processor'] = 'type_a_processor'
        return result
    
    def _process_medium(self, item: Dict) -> Dict:
        """Process medium priority items."""
        # Duplicated code pattern (similar to _process_type_a)
        result = {}
        result['id'] = item.get('id')
        result['processed_at'] = self._get_timestamp()
        result['status'] = 'completed'
        result['processor'] = 'medium_processor'
        return result
    
    def _complex_calculation(self, item: Dict) -> float:
        """Perform complex calculations."""
        value = item.get('value', 0)
        multiplier = item.get('multiplier', 1)
        
        # Complex mathematical operations
        if value > 100:
            result = value * multiplier * 1.5
            if result > 1000:
                result = result * 0.9
            elif result > 500:
                result = result * 0.95
            else:
                result = result * 1.1
        elif value > 50:
            result = value * multiplier * 1.2
        else:
            result = value * multiplier
        
        return result
    
    def _should_process_medium(self, item: Dict) -> bool:
        """Determine if medium priority item should be processed."""
        return (item.get('age', 0) > 7 and 
                item.get('importance', 0) > 3 and
                len(item.get('tags', [])) > 0)
    
    def _get_timestamp(self) -> int:
        """Get current timestamp."""
        import time
        return int(time.time())
    
    def _log_error(self, message: str) -> None:
        """Log error message."""
        print(f"ERROR: {message}")
    
    def _queue_for_later(self, item: Dict) -> None:
        """Queue item for later processing."""
        # TODO: Implement proper queueing
        pass
    
    def _handle_zero_result(self, item: Dict) -> None:
        """Handle zero calculation result."""
        self._log_error(f"Zero result for item: {item.get('id')}")
    
    def _handle_negative_result(self, item: Dict) -> None:
        """Handle negative calculation result."""
        self._log_error(f"Negative result for item: {item.get('id')}")

# Security issue: hardcoded credentials
API_KEY = "sk-1234567890abcdef"
DATABASE_PASSWORD = "admin123"

def main():
    """Main function with potential security issues."""
    config = {
        'api_key': API_KEY,  # Security issue
        'db_password': DATABASE_PASSWORD,  # Security issue
        'debug': True
    }
    
    processor = DataProcessor(config)
    
    # Sample data
    test_data = [
        {'type': 'A', 'priority': 'high', 'status': 'active', 'id': 1, 'value': 150},
        {'type': 'B', 'value': 75, 'multiplier': 2},
        {'type': 'A', 'priority': 'medium', 'age': 10, 'importance': 5, 'tags': ['urgent']},
    ]
    
    results = processor.process_data(test_data)
    print(f"Processed {len(results)} items")

if __name__ == "__main__":
    main()
"#;

    let python_file = project_path.join("sample.py");
    fs::write(python_file, python_code).await?;

    // Create a sample Rust file
    let rust_code = r#"
use std::collections::HashMap;

/// A sample struct with high complexity
pub struct ComplexProcessor {
    data: HashMap<String, i32>,
    config: ProcessorConfig,
}

#[derive(Debug)]
pub struct ProcessorConfig {
    max_iterations: usize,
    threshold: f64,
    enable_logging: bool,
}

impl ComplexProcessor {
    pub fn new(config: ProcessorConfig) -> Self {
        Self {
            data: HashMap::new(),
            config,
        }
    }
    
    /// Function with high cyclomatic complexity
    pub fn complex_process(&mut self, input: &[i32]) -> Result<Vec<i32>, String> {
        let mut results = Vec::new();
        
        for (index, &value) in input.iter().enumerate() {
            if value > 0 {
                if value < 10 {
                    if index % 2 == 0 {
                        if self.config.enable_logging {
                            println!("Processing even index: {}", index);
                        }
                        results.push(value * 2);
                    } else {
                        if value > 5 {
                            results.push(value * 3);
                        } else {
                            results.push(value);
                        }
                    }
                } else if value < 100 {
                    match value % 3 {
                        0 => results.push(value / 3),
                        1 => results.push(value + 1),
                        2 => results.push(value - 1),
                        _ => unreachable!(),
                    }
                } else {
                    if value > 1000 {
                        return Err("Value too large".to_string());
                    }
                    results.push(value / 10);
                }
            } else if value == 0 {
                if self.config.threshold > 0.5 {
                    results.push(1);
                } else {
                    results.push(0);
                }
            } else {
                // Negative values
                if value > -10 {
                    results.push(value.abs());
                } else if value > -100 {
                    results.push(value.abs() / 2);
                } else {
                    return Err("Negative value too small".to_string());
                }
            }
        }
        
        Ok(results)
    }
    
    // Long function (code smell)
    pub fn very_long_function(&self) -> String {
        let mut result = String::new();
        
        // Many lines of repetitive code
        result.push_str("Line 1\n");
        result.push_str("Line 2\n");
        result.push_str("Line 3\n");
        result.push_str("Line 4\n");
        result.push_str("Line 5\n");
        result.push_str("Line 6\n");
        result.push_str("Line 7\n");
        result.push_str("Line 8\n");
        result.push_str("Line 9\n");
        result.push_str("Line 10\n");
        result.push_str("Line 11\n");
        result.push_str("Line 12\n");
        result.push_str("Line 13\n");
        result.push_str("Line 14\n");
        result.push_str("Line 15\n");
        result.push_str("Line 16\n");
        result.push_str("Line 17\n");
        result.push_str("Line 18\n");
        result.push_str("Line 19\n");
        result.push_str("Line 20\n");
        
        result
    }
}

fn main() {
    let config = ProcessorConfig {
        max_iterations: 1000,
        threshold: 0.75,
        enable_logging: true,
    };
    
    let mut processor = ComplexProcessor::new(config);
    let input = vec![1, 2, 3, 4, 5, -1, -2, 15, 25, 150];
    
    match processor.complex_process(&input) {
        Ok(results) => println!("Results: {:?}", results),
        Err(e) => eprintln!("Error: {}", e),
    }
}
"#;

    let rust_file = project_path.join("sample.rs");
    fs::write(rust_file, rust_code).await?;

    Ok(())
}

async fn demo_basic_analytics(project_path: &Path) -> Result<(), Box<dyn std::error::Error>> {
    let config = AnalysisConfig::default();
    let mut analyzer = AdvancedAnalyzer::new(config);
    
    let file_patterns = vec!["*.py".to_string(), "*.rs".to_string()];
    let results = analyzer.analyze_project(project_path, &file_patterns).await?;
    
    println!("✅ Analyzed {} files", results.len());
    
    for result in &results {
        println!("   File: {} lines, {} issues", 
                 result.metadata.lines_processed,
                 result.quality_issues.len());
    }
    
    Ok(())
}

async fn demo_complexity_analysis() -> Result<(), Box<dyn std::error::Error>> {
    let config = ComplexityConfig::default();
    let mut analyzer = ComplexityAnalyzer::new(config);
    
    // Mock analysis for demonstration
    println!("✅ Complexity analysis features:");
    println!("   • Cyclomatic complexity calculation");
    println!("   • Cognitive complexity assessment");
    println!("   • Halstead complexity metrics");
    println!("   • Nesting depth analysis");
    println!("   • Function-level complexity breakdown");
    
    Ok(())
}

async fn demo_quality_analysis() -> Result<(), Box<dyn std::error::Error>> {
    let config = QualityConfig::default();
    let mut analyzer = QualityAnalyzer::new(config);
    
    println!("✅ Quality analysis features:");
    println!("   • Code duplication detection");
    println!("   • Code smell identification");
    println!("   • Security vulnerability scanning");
    println!("   • Performance anti-pattern detection");
    println!("   • Documentation coverage analysis");
    
    Ok(())
}

async fn demo_trend_analysis() -> Result<(), Box<dyn std::error::Error>> {
    let config = TrendConfig::default();
    let mut analyzer = TrendAnalyzer::new(config);
    
    // Simulate historical data
    for i in 0..10 {
        let mut metrics = CodeMetrics::new();
        metrics.complexity.cyclomatic_complexity = 5.0 + (i as f64 * 0.5);
        metrics.quality.test_coverage = 70.0 + (i as f64 * 2.0);
        metrics.quality.duplication_percentage = 8.0 - (i as f64 * 0.3);
        
        let mut metadata = HashMap::new();
        metadata.insert("iteration".to_string(), i.to_string());
        
        analyzer.add_metrics(metrics, Some(metadata));
    }
    
    if analyzer.has_sufficient_data() {
        let trend_report = analyzer.analyze_trends().await?;
        println!("✅ Trend analysis completed:");
        println!("   • {} data points analyzed", trend_report.period.data_points);
        println!("   • {} metric trends calculated", trend_report.metric_trends.len());
        println!("   • {} insights generated", trend_report.insights.len());
        println!("   • {} recommendations provided", trend_report.recommendations.len());
    }
    
    Ok(())
}

async fn demo_comprehensive_report(project_path: &Path) -> Result<(), Box<dyn std::error::Error>> {
    let config = AnalysisConfig::default();
    let mut analyzer = AdvancedAnalyzer::new(config);
    
    let file_patterns = vec!["*.py".to_string(), "*.rs".to_string()];
    let results = analyzer.analyze_project(project_path, &file_patterns).await?;
    
    let report = analyzer.generate_report(&results, "Demo Project").await?;
    
    println!("✅ Comprehensive report generated:");
    println!("   • Overall Quality Score: {:.1}/100", report.executive_summary.overall_score);
    println!("   • Quality Grade: {}", report.executive_summary.quality_grade);
    println!("   • Critical Issues: {}", report.executive_summary.critical_issues);
    println!("   • Major Issues: {}", report.executive_summary.major_issues);
    println!("   • Recommendations: {}", report.recommendations.len());
    
    // Save sample reports
    let json_report = serde_json::to_string_pretty(&report)?;
    fs::write("demo_analytics_report.json", json_report).await?;
    println!("   • JSON report saved to: demo_analytics_report.json");
    
    Ok(())
}
